#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>

static void manejador_sigchld (int signum);

int
main ()
{
    int                       sk,
                              sk_aceptado;
    struct sockaddr_in        sk_addr;
    pid_t                     pid;
    char                      buf [32];
    
    /*
     * se crea el socket para recibir las conexiones
     */
    
        sk_addr.sin_family = AF_INET;
        sk_addr.sin_addr.s_addr = INADDR_ANY;
        sk_addr.sin_port = htons (2345);
        
        if ((sk = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
            perror ("socket");
            return 1;
        }
        
        if (bind (sk, (struct sockaddr *) &sk_addr, sizeof (struct sockaddr)) == -1) {
            perror ("bind");
            close (sk);
            return 1;
        }
        
        if (listen (sk, SOMAXCONN)) {
            perror ("listen");
            close (sk);
            return 1;
        }
     
    /*
     * se crea el demonio
     */
    
        pid = fork ();
        if (pid < 0)
            return 1;
        else if (pid > 0)
            return 0;
        
        /* umask (0); */
        
        /* abrir logs */
        
        if (setsid () == -1) {
            return 1;
        }
        
        /*
        close (STDIN_FILENO);
        close (STDOUT_FILENO);
        close (STDERR_FILENO);
        */
    
    /*
     * se coloca un manejador para la señal SIGCHLD
     */

        signal (SIGCHLD, *manejador_sigchld);
    
    /*
     * el programa propiamente dicho
     */
        
        for (;;) {
            sk_aceptado = accept (sk, NULL, 0);
            if (sk_aceptado == -1) {
            } else {
                /* se crea un proceso para atender cada socket nuevo */
                pid = fork ();
                if (pid < 0) {
                } else if (pid == 0) {
                    sprintf (buf, "%d", sk_aceptado);
                    execl ("lanchat2.tk", "lanchat2.tk", buf, NULL);
                }
                
                close (sk_aceptado);
            }
        }
}

/*
 * el manejador para la señal SIGCHLD
 */

static void
manejador_sigchld (int signum)
{
    int estado;
    
    wait (&estado);
}

